#Prints out files in MQO format

from Sanae3D.lib.ModelObject import Model3D
from Sanae3D.lib.StructReader import StructReader

class MQO_Parser(Model3D):
    '''An MQO Object. Can read files in MQO format and export objects in
    MQO format. Inherits from the generic Model3D class'''
    
    def __init__(self, obj3D=None, inFile=None, outFile=None):
        '''Initialize am MQO Object.'''
        
        super(MQO_Parser, self).__init__("MQO")
        self.obj3D = obj3D
        self.inFile = inFile
        self.outFile = outFile

    #import functions
    
    def get_value(self, line, delimStart, delimEnd):
        
        start = line.find(delimStart) + 1
        end = line.find(delimEnd, start)
        return line[start:end]
    
    def parse_materials(self, matCount):
        
        for i in xrange(0, matCount):
            line = self.inFile.readline().strip()
            self.create_material(i)
            
            #get material name
            matName = self.get_value(line, '"', '"')
            self.add_material_name(i, matName)
            
            colorIndex = line.find("col")
            if colorIndex != -1:
                rgba = self.get_value(line[colorIndex:], '(', ')').split(" ")
                self.add_rgba(i, rgba[:])
                
            difIndex = line.find("dif")
            if difIndex != -1:
                dif = self.get_value(line[difIndex:], "(", ")").split()
                self.add_diffuse(i, dif[:])
                
            emiIndex = line.find("emi")
            if emiIndex != -1:
                emi = self.get_value(line[emiIndex:], "(", ")").split()
                self.add_emissive(i, emi)
                
            spcIndex = line.find("spc")
            if spcIndex != -1:
                spc = self.get_value(line[spcIndex:], "(", ")").split()
                self.add_specular(i, spc)
                
            ambIndex = line.find("amb")
            if ambIndex != -1:
                amb = self.get_value(line[ambIndex:], "(", ")").split()
                self.add_ambient(i, amb)
            
            #get texture name
            texIndex = line.find("tex")
            if texIndex != -1:
                texName = self.get_value(line[texIndex:], '"', '"')
                self.add_texture_name(i, texName)
                
    def parse_faces(self, objName):
        
        line = self.inFile.readline()
        faceCount = int(line.split()[1])
        for faceNum in xrange(0, faceCount):          
            self.create_face(objName, faceNum)
            
            line = self.inFile.readline()
            #get vertices
            verts = self.get_value(line, "(", ")").split()
            self.add_face_verts(objName, faceNum, verts)
            
            #get material number
            matOffset = line.find("M")
            if matOffset != -1:
                matNum = self.get_value(line[matOffset:], "(", ")")
                self.add_face_material(objName, faceNum, matNum)
            
            #get UV
            uvOffset = line.find("UV")
            if uvOffset != -1:
                uv = self.get_value(line[uvOffset:], "(", ")").split()
                self.add_face_uv(objName, faceNum, uv)
        
    def parse_vertices(self, line, objName):
        
        vertCount = int(line.split()[1])
        for i in xrange(0, vertCount):
            coords = self.inFile.readline().strip().split()
            self.create_vertex(objName, i)
            self.add_coords(objName, i, coords)
        #close brace
        line = self.inFile.readline()
        
    def parse_objects(self, line):
        
        objName = self.get_value(line, '"', '"')
        self.create_object(objName)
        line = self.skip_lines("vertex")
        self.parse_vertices(line, objName)
        self.parse_faces(objName)

    def parse_MQO(self):
        
        line = self.inFile.readline()
        while line:
            line = line.strip()
            if line.startswith("Scene"):
                pass
            if line.startswith("Material"):
                matCount = int(line.split()[1])
                self.parse_materials(matCount)
            elif line.startswith("Object"):
                self.parse_objects(line)
            line = self.inFile.readline()
            
class MQO_Writer(Model3D):
    
    def __init__(self, obj3D=None, inFile=None, outFile=None):
        
        super(MQO_Writer, self).__init__("MQO")
        self.obj3D = obj3D
        self.inFile = inFile
        self.outFile = outFile
        
    def print_materials(self):
        '''Print the material section'''
        
        matNum = self.obj3D.mat_count()
        if matNum:
            self.outFile.write("Material %s {\n" %matNum)
            for i in xrange(0, matNum):
                name = self.obj3D.get_material_name(i)
                temp = self.obj3D.get_material_texture(i)
                texture = ""
                if temp:
                    texture = 'tex("%s")' %temp
                
                t = self.obj3D.get_rgba(i)
                if t:
                    rgba = '%.4f %.4f %.4f %.4f' %(t[0], t[1], t[2], 1.000)
                else:
                    rgba = "1.000 1.000 1.000 1.000"
                    
                diffuse = self.obj3D.get_diffuse(i)
                if isinstance(diffuse, list):
                    diffuse = "%.4f" %abs(diffuse[0])
                else:
                    diffuse = "1.000"

                ambient = self.obj3D.get_ambient(i)
                if isinstance(ambient, list):
                    ambient = "%.4f" %abs(ambient[0])
                else:
                    ambient = "1.000"
                
                emissive = self.obj3D.get_emissive(i)
                if isinstance(emissive, list):
                    emissive = "%.4f" %abs(emissive[0])
                else:
                    emissive = "0.800"
                
                specular = self.obj3D.get_specular(i)
                if isinstance(specular, list):
                    specular = "%.4f" %abs(specular[0])
                else:
                    specular = "0.000"
                    
                power = self.obj3D.get_power(i)
                    
                string = '\t"%s" shader(3) col(%s) dif(%s) amb(%s) emi(%s) spc(%s) power(%s) %s\n' %(name, rgba, diffuse, ambient, emissive, specular, power, texture)
                self.outFile.write(string)
            self.outFile.write('}\n')
        
    def print_faces(self, objName):
    
        numFaces = self.obj3D.face_count(objName)
        self.outFile.write("\tface %s {\n" %numFaces)
        for i in xrange(0, numFaces):
            
            material = self.obj3D.get_face_mat(objName, i)
            verts = self.obj3D.get_face_verts(objName, i)
            strVerts = ' '.join(["%s" %x for x in verts])
            vertCount = len(verts)
            
            #get UV values
            uv = []
            temp_uv = self.obj3D.get_uv(objName, i)
            if temp_uv:
                uv = ' '.join(["%.6f" % x for x in temp_uv])
            else:
                uv = ' '.join(["1.00000"] * vertCount * 2)
                 
            if vertCount > 4:
                continue
                
            outStr = "\t\t%s V(%s)" %(vertCount, strVerts)
            if material != -1:
                outStr = ''.join([outStr, " M(%s)" %material])
            if uv:
                outStr = ''.join([outStr, " UV(%s)" %uv])
            self.outFile.write(''.join([outStr, "\n"]))
        self.outFile.write("\t}\n")
        self.outFile.write("}\n")
        
    def print_vertices(self, objName):
        '''Print unique vertices'''
        
        vertices = self.obj3D.get_vertices(objName)
        vertCount = len(vertices)
        self.outFile.write("\tvertex %s {\n" %vertCount)
        for i in xrange(0, vertCount):
            temp = self.obj3D.get_coords(objName, i)
            temp[0] *= -1
            coords = ' '.join(["%.4f" %x for x in temp])
            self.outFile.write("\t\t%s\n" %coords)
        
    def print_objects(self):
        '''Prints out objects'''
        
        #self.obj3D.transform_meshes()
        objNames = self.obj3D.get_objects()
        for objName in objNames:
            self.outFile.write('Object "%s" {\n' %objName)
            self.outFile.write("\tdepth 0\n")
            self.outFile.write("\tfolding 0\n")
            self.outFile.write("\tscale 1.000000 1.000000 1.000000\n")
            self.outFile.write("\trotation 0.000000 0.000000 0.000000\n")
            self.outFile.write("\ttranslation 0.000000 0.000000 0.000000\n")
            self.outFile.write("\tvisible 15\n")
            self.outFile.write("\tlocking 0\n")
            self.outFile.write("\tshading 1\n")
            self.outFile.write("\tfacet 59.5\n")
            self.outFile.write("\tcolor 0.677 0.672 0.742\n")
            self.outFile.write("\tcolor_type 1\n")
            self.print_vertices(objName)
            self.outFile.write("\t}\n")
            self.print_faces(objName)
    
    def print_MQO(self):
        '''Print MQO format'''
        
        self.outFile.write("Metasequoia Document\nFormat Text Ver 1.0\n\n")
        
        #print scene
        self.outFile.write("Scene {\n")
        self.outFile.write("\tpos -1.3969 -22.7511 1500.0000\n")
        self.outFile.write("\tlookat 0.0000 0.0000 0.0000\n")
        self.outFile.write("\thead -23.7036\n")
        self.outFile.write("\tpich -0.0064\n")
        self.outFile.write("\tortho 0\n")
        self.outFile.write("\tzoom2 12.8000\n")
        self.outFile.write("\tamb 0.250 0.250 0.250\n")
        self.outFile.write("}\n")
        self.print_materials()
        self.print_objects()
        self.outFile.write("Eof\n")
        
def read_file(path):
    '''Parses an MQO file and returns an MQO object'''
    
    openFile = open(path)
    obj = MQO_Parser("MQO", inFile=openFile)
    obj.parse_MQO()
    openFile.close()
    return obj

def write_file(filename, modelObj):
    '''Takes a Model3D object and creates an MQO'''
    
    write_file = open(filename + ".mqo", "w")
    mqoObj = MQO_Writer(obj3D=modelObj, outFile=write_file)
    mqoObj.print_MQO()
    write_file.close()
    
def definitions():
    
    return "Metaseq", "MQO", "Metasequoia MQO"
    
if __name__ == '__main__':
    
    filename = "Item_001.mqo"
    obj = read_file(filename)
    #write_mqo("output", obj)